package org.iipg.service.core.controller;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.iipg.common.data.dto.BaseInfoDto;
import org.iipg.common.data.dto.PageDto;
import org.iipg.common.data.exception.PhException;
import org.iipg.common.data.vo.PhResponse;
import org.iipg.service.core.dto.CreateIndexDto;
import org.iipg.service.core.dto.DocumentDto;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author zhuhy163@163.com
 * @Description
 * @date 2021/7/16 上午10:36
 */
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(value = "ES测试接口", tags = {"ES测试接口"})
@RequestMapping("es")
public class ESDemoController {

    private final RestHighLevelClient restHighLevelClient;

    /**
     * 创建索引
     */
    @ApiOperation(value = "创建索引", produces = "application/json")
    @RequestMapping(value = "/createIndex", method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE})
    public PhResponse<String> createIndex(@RequestBody CreateIndexDto createIndexDto) {
        CreateIndexRequest request = new CreateIndexRequest(createIndexDto.getName());
        String result = "";
        try {
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            result = createIndexResponse.index();
        } catch (Exception e) {
            log.warn(e.getMessage());
            throw new PhException(e.getMessage());
        }

        return PhResponse.ok(result);
    }

    /**
     * 添加BaseInfo
     */
    @ApiOperation(value = "添加BaseInfo", produces = "application/json")
    @RequestMapping(value = "/addBaseInfo", method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE})
    public PhResponse<RestStatus> addBaseInfo(@RequestParam("name") String name, @RequestBody DocumentDto<BaseInfoDto> documentDto) {

        RestStatus result = null;

        try {
            //创建请求
            IndexRequest request = new IndexRequest(name);

            //设置超时时间
            request.timeout(TimeValue.timeValueSeconds(1));
            //request.timeout("1s");

            //设置刷新策略
            request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL);

            //设置操作为新增
            request.opType(DocWriteRequest.OpType.INDEX);

            //将我们的数据放入请求 json
            JSONObject object = new JSONObject();
            object.put("baseInfo", documentDto.getDocument());
            request.source(JSON.toJSONString(object), XContentType.JSON);
            //客户端发送请求 , 获取响应的结果
            IndexResponse indexResponse = restHighLevelClient.index(request,
                    RequestOptions.DEFAULT);

            log.debug(indexResponse.toString()); //打印文档的内容

            log.info(JSON.toJSONString(indexResponse.status()));

            result = indexResponse.status();

        } catch (Exception e) {
            log.warn(e.getMessage());
            throw new PhException(e.getMessage());
        }

        return PhResponse.ok(result);
    }

    /**
     * 查询BaseInfo
     */
    @ApiOperation(value = "查询BaseInfo", produces = "application/json")
    @RequestMapping(value = "/queryBaseInfo", method = RequestMethod.POST,
            produces = {MediaType.APPLICATION_JSON_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE})
    public PhResponse<PageDto<BaseInfoDto>> queryBaseInfo(@RequestParam("name") String name, @RequestBody DocumentDto<BaseInfoDto> documentDto) {

        PageDto<BaseInfoDto> result = new PageDto<>();

        try {
            SearchRequest searchRequest = new SearchRequest(name);
            // 构建搜索条件
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            // 查询条件，我们可以使用 QueryBuilders 工具来实现
            // QueryBuilders.termQuery 精确
            // QueryBuilders.matchAllQuery() 匹配所有
            TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("baseInfo.basicInformation.issuerDN",
                    "aaa");
            //MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
            sourceBuilder.query(termQueryBuilder);
            sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

            searchRequest.source(sourceBuilder);
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest,
                    RequestOptions.DEFAULT);

            result.setTotal(searchResponse.getHits().getTotalHits().value);

            List<BaseInfoDto> list = new ArrayList<>();
            for (SearchHit documentFields : searchResponse.getHits().getHits()) {
                BaseInfoDto baseInfoDto = new BaseInfoDto();
                BeanUtil.fillBeanWithMap((Map) documentFields.getSourceAsMap().get("baseInfo"), baseInfoDto, true);
                list.add(baseInfoDto);
            }
            result.setRecords(list);
        } catch (Exception e) {
            log.warn(e.getMessage());
            throw new PhException(e.getMessage());
        }

        return PhResponse.ok(result);
    }

}
